package com.duck.duckchatbackend.controller;

import java.util.List;

import com.duck.duckchatbackend.annotation.GlobalInterceptor;
import com.duck.duckchatbackend.entity.dto.TokenUserInfoDto;
import com.duck.duckchatbackend.entity.dto.UserContactSearchResultDto;
import com.duck.duckchatbackend.entity.enums.PageSize;
import com.duck.duckchatbackend.entity.enums.ResponseCodeEnum;
import com.duck.duckchatbackend.entity.enums.UserContactStatusEnum;
import com.duck.duckchatbackend.entity.enums.UserContactTypeEnum;
import com.duck.duckchatbackend.entity.po.UserContactApply;
import com.duck.duckchatbackend.entity.po.UserInfo;
import com.duck.duckchatbackend.entity.query.UserContactApplyQuery;
import com.duck.duckchatbackend.entity.query.UserContactQuery;
import com.duck.duckchatbackend.entity.po.UserContact;
import com.duck.duckchatbackend.entity.vo.PaginationResultVO;
import com.duck.duckchatbackend.entity.vo.ResponseVO;
import com.duck.duckchatbackend.entity.vo.UserInfoVO;
import com.duck.duckchatbackend.exception.BusinessException;
import com.duck.duckchatbackend.service.UserContactApplyService;
import com.duck.duckchatbackend.service.UserContactService;
import com.duck.duckchatbackend.service.UserInfoService;
import com.duck.duckchatbackend.utils.CopyTools;
import jodd.util.ArraysUtil;
import org.apache.catalina.User;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

/**
 * 联系人 Controller
 */
@RestController
@RequestMapping("/contact")
public class UserContactController extends ABaseController{

	@Resource
	private UserContactService userContactService;

	@Resource
	private UserInfoService userInfoService;

	@Resource
	private UserContactApplyService userContactApplyService;

	/**
	 * 处理搜索请求的控制器方法
	 * 该方法使用@RequestMapping注解来映射/search URL的请求
	 * 通过@GlobalInterceptor注解应用全局拦截器
	 *
	 * @param request HttpServletRequest对象，包含请求相关的信息
	 * @param contactId 需要搜索的联系人ID，使用@NotEmpty注解确保参数不为空
	 * @return 返回一个ResponseVO对象，包含搜索结果
	 */
	@RequestMapping("/search")
	@GlobalInterceptor
	public ResponseVO search(HttpServletRequest request, @NotEmpty String contactId) {
	    // 从请求中获取用户信息
	    TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);
	    // 调用服务层方法搜索联系人
	    UserContactSearchResultDto resultDto = userContactService.searchContact(tokenUserInfoDto.getUserId(),contactId);
	    // 返回包含搜索结果的成功响应
	    return getSuccessResponseVO(resultDto);
	}

	/**
	 * 处理添加申请的接口方法
	 *
	 * 该方法负责处理用户向系统提交的添加申请，例如加入某个群组或关注某个联系人
	 * 它通过获取用户信息、验证联系人ID和类型，以及申请信息来完成添加申请的过程
	 *
	 * @param request HTTP请求对象，用于获取用户请求的相关信息
	 * @param contactId 不为空的字符串，表示要添加的联系人的ID
	 * @param contactType 不为空的字符串，表示联系人类型，例如'friend'或'group'
	 * @param applyInfo 可选的字符串，包含申请添加时的附加信息或备注
	 * @return 返回一个ResponseVO对象，包含处理结果或错误信息
	 */
	@RequestMapping("/applyAdd")
	@GlobalInterceptor
	public ResponseVO applyAdd(HttpServletRequest request, @NotEmpty String contactId,@NotEmpty String contactType,String applyInfo) {
	    // 从请求中获取用户信息，用于验证用户身份和获取用户数据
	    TokenUserInfoDto tokenUserInfoDto =getTokenUserInfo(request);

	    // 调用业务服务层方法，处理用户的添加申请
	    Integer joinType = userContactApplyService.applyAdd(tokenUserInfoDto,contactId,contactType,applyInfo);

	    // 返回成功响应，包含处理结果
	    return getSuccessResponseVO(joinType);
	}

	/**
	 * 处理加载申请的请求
	 * 该方法用于获取用户的联系申请列表，根据最后申请时间降序排序
	 * 并且分页查询，每页显示15条记录
	 *
	 * @param request HttpServletRequest对象，用于获取用户请求信息
	 * @param pageNo 页码，用于指定查询的页数
	 * @return 返回一个包含申请列表的ResponseVO对象
	 */
	@RequestMapping("/loadApply")
	@GlobalInterceptor
	public ResponseVO loadApply(HttpServletRequest request,Integer pageNo) {
	    // 从请求中获取用户信息
	    TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);

	    // 创建查询对象，并设置查询条件
	    UserContactApplyQuery applyQuery = new UserContactApplyQuery();
	    applyQuery.setOrderBy("last_apply_time desc");
	    applyQuery.setReceiveUserId(tokenUserInfoDto.getUserId());
	    applyQuery.setPageNo(pageNo);
	    applyQuery.setPageSize(PageSize.SIZE15.getSize());
	    applyQuery.setQueryContactInfo(true);

	    // 调用服务方法，分页查询申请列表
	    PaginationResultVO resultVO =userContactApplyService.findListByPage(applyQuery);

	    // 返回成功响应，包含查询结果
	    return getSuccessResponseVO(resultVO);
	}

	/**
	 * 处理申请
	 *
	 * 该方法用于处理用户的申请，根据提供的申请ID和状态更新申请记录
	 * 主要功能包括获取用户信息、验证申请ID和状态的有效性，并调用服务层方法处理申请
	 *
	 * @param request HTTP请求对象，用于获取用户信息
	 * @param applyId 申请ID，用于标识特定的申请记录
	 * @param status 申请的状态，用于更新申请记录的状态
	 * @return 返回处理结果的ResponseVO对象
	 */
	@RequestMapping("/dealWithApply")
	@GlobalInterceptor
	public ResponseVO dealWithApply(HttpServletRequest request, @NotNull Integer applyId,@NotNull Integer status){
	    // 从请求中获取用户信息
	    TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);

	    // 调用服务层方法处理申请
	    this.userContactApplyService.dealWithApply(tokenUserInfoDto.getUserId(),applyId,status);

	    // 返回成功响应
	    return getSuccessResponseVO(null);
	}

	/**
	 * 加载用户联系人信息
	 *
	 * 根据不同的联系人类型，加载相应的联系人信息，支持用户和群组两种联系人类型
	 * 对于用户类型，直接查询用户信息；对于群组类型，查询群组信息但不包括用户自己的群组
	 *
	 * @param request HTTP请求对象，用于获取用户令牌信息
	 * @param contactType 联系人类型，不能为空，支持"user"和"group"两种类型
	 * @return 返回包含联系人列表的响应对象
	 * @throws BusinessException 当联系人类型不支持时，抛出业务异常
	 */
	@RequestMapping("/loadContact")
	@GlobalInterceptor
	public ResponseVO loadContact(HttpServletRequest request,@NotNull String contactType) {
	    // 根据联系人类型名称获取对应的枚举对象
	    UserContactTypeEnum contactTypeEnum = UserContactTypeEnum.getByName(contactType);
	    // 如果联系人类型不存在，抛出业务异常
	    if(contactTypeEnum==null){
	        throw  new BusinessException(ResponseCodeEnum.CODE_600);
	    }
	    // 从请求中获取用户令牌信息
	    TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);
	    // 创建用户联系人查询对象
	    UserContactQuery contactQuery = new UserContactQuery();
	    // 设置查询的用户ID
	    contactQuery.setUserId(tokenUserInfoDto.getUserId());
	    // 设置联系人类型
	    contactQuery.setContactType(contactTypeEnum.getType());
	    // 根据联系人类型设置查询参数
	    if(contactTypeEnum.USER == contactTypeEnum){
			contactQuery.setQueryContactUserInfo(true);
	    } else if (contactTypeEnum.GROUP == contactTypeEnum) {
			contactQuery.setQueryGroupInfo(true);
	        contactQuery.setExcludeMyGroup(true);
	    }
	    // 设置查询结果的排序方式
	    contactQuery.setOrderBy("last_update_time desc");
	    // 设置查询的状态数组，包括好友、删除和黑名单状态
	    contactQuery.setStatusArray(new Integer[]{
	            UserContactStatusEnum.FRIEND.getStatus(),
	            UserContactStatusEnum.DEL_BE.getStatus(),
	            UserContactStatusEnum.BLACKLIST_BE.getStatus(),
	    });
	    // 根据查询参数获取联系人列表
	    List<UserContact> contactList = userContactService.findListByParam(contactQuery);
	    // 返回成功的响应对象，包含联系人列表
	    return getSuccessResponseVO(contactList);
	}



	/**
	 * 根据联系人ID获取联系人信息
	 * 此方法首先从请求中获取用户令牌信息，然后根据联系人ID获取用户信息，
	 * 并检查当前用户与该联系人的关系状态
	 *
	 * @param request HTTP请求对象，用于获取用户令牌信息
	 * @param contactId 联系人ID，不能为空
	 * @return 返回包含联系人信息和关系状态的响应对象
	 */
	@RequestMapping("/getContactInfo")
	@GlobalInterceptor
	public ResponseVO getContactInfo(HttpServletRequest request, @NotEmpty String contactId) {
		// 从请求中获取用户令牌信息
		TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);
		// 根据联系人ID获取用户信息
		UserInfo userInfo = userInfoService.getUserInfoByUserId(contactId);
		// 将用户信息复制到用户信息视图对象中
		UserInfoVO userInfoVO = CopyTools.copy(userInfo, UserInfoVO.class);
		// 默认设置联系人状态为非好友
		userInfoVO.setContactStatus(UserContactStatusEnum.NOT_FRIEND.getStatus());
		// 根据用户ID和联系人ID获取用户联系人信息
		UserContact userContact = userContactService.getUserContactByUserIdAndContactId(tokenUserInfoDto.getUserId(), contactId);
		// 如果用户联系人信息不为空，则更新联系人状态
		if (userContact != null) {
			userInfoVO.setContactStatus(userContact.getStatus());
		}
		// 返回成功响应，包含用户信息视图对象
		return getSuccessResponseVO(userInfoVO);
	}

	/**
	 * 根据联系人ID获取联系人用户信息
	 * 该方法首先验证请求中的联系人ID是否有效，然后根据当前用户的ID和提供的联系人ID
	 * 从服务层获取用户联系人信息，进一步验证联系人的状态是否满足预定义的条件
	 * 最后，根据联系人ID获取并返回用户的详细信息
	 *
	 * @param request HTTP请求对象，用于获取当前请求的上下文信息
	 * @param contactId 联系人用户ID，用于查询联系人信息和用户信息
	 * @return 返回一个包含联系人用户信息的ResponseVO对象
	 * @throws BusinessException 如果联系人信息不存在或状态不符合条件，则抛出业务异常
	 */
	@RequestMapping("/getContactUserInfo")
	@GlobalInterceptor
	public ResponseVO getContactUserInfo(HttpServletRequest request, @NotEmpty String contactId) {
	    // 从请求中获取当前用户的令牌信息
	    TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);
	    // 根据当前用户的ID和联系人ID获取用户联系人信息
	    UserContact userContact = this.userContactService.getUserContactByUserIdAndContactId(tokenUserInfoDto.getUserId(), contactId);
	    // 验证联系人信息是否存在且状态是否满足条件
	    if (null == userContact || !ArraysUtil.contains(new Integer[]{
	            UserContactStatusEnum.FRIEND.getStatus(),
	            UserContactStatusEnum.DEL_BE.getStatus(),
	            UserContactStatusEnum.BLACKLIST_BE.getStatus(),
	            UserContactStatusEnum.BLACKLIST_BE_FIRST.getStatus()}, userContact.getStatus())) {
	        throw new BusinessException(ResponseCodeEnum.CODE_600);
	    }
	    // 根据联系人ID获取用户信息
	    UserInfo userInfo = userInfoService.getUserInfoByUserId(contactId);
	    // 将用户信息复制到视图对象中
	    UserInfoVO userInfoVO = CopyTools.copy(userInfo, UserInfoVO.class);
	    // 返回包含用户信息的成功响应
	    return getSuccessResponseVO(userInfoVO);
	}
	@RequestMapping("/delContact")
	@GlobalInterceptor
	public ResponseVO delContact(HttpServletRequest request,@NotNull String contactId){
		  TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);
          userContactService.removeUserContact(tokenUserInfoDto.getUserId(),contactId,UserContactStatusEnum.DEL);
		  return  getSuccessResponseVO(null);
	}
	@RequestMapping("/addContact2BlackList")
	@GlobalInterceptor
	public ResponseVO addContact2BlackList(HttpServletRequest request,@NotNull String contactId){
		TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);
		userContactService.removeUserContact(tokenUserInfoDto.getUserId(),contactId,UserContactStatusEnum.BLACKLIST);
		return  getSuccessResponseVO(null);
	}
}